package activator;

import http.LibraryContext;
import http.LibraryServlet;

import javax.servlet.ServletException;

import library.service.Book;
import library.service.LibraryService;

import org.osgi.framework.BundleActivator;
import org.osgi.framework.BundleContext;
import org.osgi.framework.Constants;
import org.osgi.framework.ServiceEvent;
import org.osgi.framework.ServiceListener;
import org.osgi.framework.ServiceReference;
import org.osgi.service.http.HttpService;
import org.osgi.service.http.NamespaceException;

public class HttpActivator implements BundleActivator, ServiceListener {

	// --- Members -------------------------------------------------------------

	BundleContext bundleContext;
	// httpService stuff
	ServiceReference httpSrvcRef;
	HttpService httpService;
	LibraryServlet libraryServlet;
	// libraryService stuff
	ServiceReference libraryServiceRef;
	LibraryService libraryService;

	// constants
	private static final String SERVLET_ALIAS = "/library";
	private static final String IMAGE_ALIAS = "/res";
	private static final String SEARCH_BOOK_NAME = "Java";
	private static final String SEARCH_BOOK_CATEGORY = "technical";

	// --- Implementation BundleActivator interface ----------------------------
	public void start(BundleContext bundleContext) throws Exception {
		this.bundleContext = bundleContext;

		// create Servlet instance
		libraryServlet = new LibraryServlet();

		// get LibraryServiceReference and LibraryService
		while (libraryServiceRef == null) {
			ServiceReference[] libraryServiceRefArray = bundleContext
					.getServiceReferences(LibraryService.class.getName(),
							generateBookFilter());
			if (libraryServiceRefArray != null) {
				libraryServiceRef = libraryServiceRefArray[0];
				libraryService = (LibraryService) bundleContext
						.getService(libraryServiceRef);
			}
		}

		// get Http ServiceReference
		ServiceReference httpServiceRef = bundleContext
				.getServiceReference(HttpService.class.getName());
		if (httpServiceRef != null) {
			getHttp(httpServiceRef);
		}

		// add serviceListener with filter
		bundleContext.addServiceListener(this, generateHttpFilter());
	}

	public void stop(BundleContext bundleContext) throws Exception {
		// clean up HttpService stuff
		if (httpSrvcRef != null) {
			// unregister and clear HttpServiceResources, HttpService,
			// ServiceReference
			cleanUpHttpResources();
		}
		libraryServlet = null;
		// remove service listener
		bundleContext.removeServiceListener(this);

		// clean up LibraryService stuff
		cleanUpLibraryServiceResources();

		bundleContext = null;
	}

	// --- Auxiliary methods ---------------------------------------------------
	private void getHttp(ServiceReference srvcRef) {

		httpService = (HttpService) bundleContext.getService(srvcRef);

		if (httpService != null) {
			httpSrvcRef = srvcRef;

			try {
				// set book if it is found
				libraryServlet.setFoundBook(findBook());

				// register servlet
				LibraryContext libraryContext = new LibraryContext();
				httpService.registerServlet(SERVLET_ALIAS, libraryServlet,
						null, libraryContext);
				httpService.registerResources(IMAGE_ALIAS, "/resources",
						libraryContext);
				System.out.println("Library Servlet registered!");
			} catch (ServletException e) {
				e.printStackTrace();
			} catch (NamespaceException e) {
				e.printStackTrace();
			}

		}

	}

	private Book findBook() {
		Book foundBook = null;
		if (libraryService != null) {
			foundBook = libraryService.findBookByName(SEARCH_BOOK_NAME);
		}
		System.out.println("Found book: " + foundBook);
		return foundBook;
	}

	/**
	 * Unregisters and clears HttpServiceResources, HttpService,
	 * ServiceReference
	 */
	private void cleanUpHttpResources() {
		httpService.unregister(SERVLET_ALIAS);
		httpService.unregister(IMAGE_ALIAS);
		bundleContext.ungetService(httpSrvcRef);
		httpService = null;
		httpSrvcRef = null;
		System.out.println("Library Servlet unregistered!");
	}

	private void cleanUpLibraryServiceResources() {
		if (libraryService != null) {
			bundleContext.ungetService(libraryServiceRef);
			libraryService = null;
			libraryServiceRef = null;
		}
		System.out.println("Library Service unregistered!");
	}

	private String generateBookFilter() {
		String filter = "(category=" + SEARCH_BOOK_CATEGORY + ")";
		filter = "(&" + filter + "(" + Constants.OBJECTCLASS + "="
				+ LibraryService.class.getName() + "))";
		System.out.println("BookFilter: " + filter);
		return filter;
	}

	private String generateHttpFilter() {
		String filter = "(" + Constants.OBJECTCLASS + "="
				+ HttpService.class.getName() + ")";
		System.out.println("HttpFilter: " + filter);
		return filter;
	}

	// --- Implementation ServiceListener interface ----------------------------
	public void serviceChanged(ServiceEvent serviceEvent) {

		switch (serviceEvent.getType()) {
		case ServiceEvent.REGISTERED: {
			if (httpSrvcRef == null) {
				getHttp(serviceEvent.getServiceReference());
			}
			break;
		}
		case ServiceEvent.UNREGISTERING: {
			ServiceReference tempSrvcRef = serviceEvent.getServiceReference();
			if (tempSrvcRef.equals(httpSrvcRef)) {
				// Unregisters and clears HttpServiceResources,
				// HttpService,ServiceReference
				cleanUpHttpResources();
			}
			break;
		}
		}
	}
}
